﻿using Castle.DynamicProxy;
using Core.Proxy.Attributes.InterceptorAttributes.BaseAttributes;
using Core.Proxy.Enums;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using NPOI.HPSF;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Core.Proxy.Utils
{
    internal class AutoFacHelper
    {
        private static ConcurrentDictionary<string, IConfiguration> configMap=new ConcurrentDictionary<string, IConfiguration>();
        public static IConfiguration GetConfiguration(string fileName)
        {
            if(configMap.TryGetValue(fileName,out IConfiguration result))
            {
                return result;
            }
            else
            {
				var builder = new ConfigurationBuilder()
						   .SetBasePath(Directory.GetCurrentDirectory())
						   .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
				var configuration = builder.Build();
				configMap.TryAdd(fileName, configuration);
                return configuration;
			}
        }
		/// <summary>
		/// 从BaseCacheAttribute实例上获取缓存的key
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="invocation"></param>
		/// <param name="attr"></param>
		/// <returns></returns>
		public static string GetKey<T>(IInvocation invocation, T attr,string constKey=null) where T : BaseCacheAttribute
        {
            try
            {
                var methodParamNames = invocation.MethodInvocationTarget.GetParameters().Select(t=>t.Name).ToList();
                StringBuilder sb;
                if (constKey == null)
                {
                    sb = new StringBuilder($"{attr.ConstKey}_");
                }
                else
                {
                    sb = new StringBuilder($"{constKey}:{attr.ConstKey}_");
                }
                switch (attr.CacheKeyPrefix)
                {
                    case CacheKeyPrefix.ClassName:
                        sb.Append($"className:{invocation.TargetType.FullName}_");
                        break;
                    case CacheKeyPrefix.ClassNameAndMethodName:
                        sb.Append($"className:{invocation.TargetType.FullName}_methodName:{invocation.MethodInvocationTarget.Name}_");
                        break;
                    case CacheKeyPrefix.None:
                        break;
                    default:
                        break;
                }
                foreach (var item in attr.DynamicParamKeys)
                {
                    string[] splitStrings = item.Split(".");
                    string paramName = splitStrings[0];
                    int index= methodParamNames.IndexOf(paramName);
                    if (index == -1)
                    {
                        throw new ArgumentException("dynamickey is not exists!");
                    }
                    var argValue = invocation.GetArgumentValue(index);
                    if (splitStrings.Length > 1)
                    {
                        object propertyValue = argValue;
                        StringBuilder propertyKey = new StringBuilder();
                        for (int i = 1; i < splitStrings.Length; i++)
                        {
                            var property = propertyValue.GetType().GetProperty(splitStrings[i]);
                            if (property == null)
                            {
                                throw new ArgumentException($"dynamickey property is not exists!value:{item}");
                            }
                            propertyValue = property.GetValue(propertyValue);
                            if(propertyValue == null)
                            {
                                break;
                            }
                            propertyKey.Append($"{splitStrings[i]}.");
                            if(i==splitStrings.Length - 1)
                            {
                                if(!propertyValue.GetType().IsValueType && propertyValue.GetType() != typeof(string))
                                {
                                    sb.Append($"{propertyKey.ToString().TrimEnd('.')}:{JsonConvert.SerializeObject(propertyValue)}_");
                                }
                                else
                                {
                                    sb.Append($"{propertyKey.ToString().TrimEnd('.')}:{propertyValue}_");
                                }
                            }
                        }
                    }
                    else
                    {
                        if (!argValue.GetType().IsValueType && argValue.GetType() != typeof(string))
                        {
                            sb.Append($"{splitStrings[0]}:{JsonConvert.SerializeObject(argValue)}_");
                        }
                        else
                        {
                            sb.Append($"{splitStrings[0]}:{argValue}_");
                        }
                    }

                }
                return sb.ToString().TrimEnd('_');
            }
            catch(Exception e)
            {
                throw new ArgumentException(e.Message);
            }
        }
        /// <summary>
        /// 获取type的默认值
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object GetDefaultValue(Type type)
        {
            if (Nullable.GetUnderlyingType(type) != null)
            {
                return null;
            }
            return type.IsValueType ? Activator.CreateInstance(type) : null;
        }
    }
}
